#include <bits/stdc++.h>
using namespace std;
//C++11 独占
/*
*/
template <typename T>
class UniquePtr{
public:
    UniquePtr():m_data(nullptr){}
    UniquePtr(T* data):m_data(data){}
    UniquePtr(const UniquePtr<T>& other) = delete;
    UniquePtr(UniquePtr<T>&& other):m_data(other.release()){}
    ~UniquePtr(){
        if(m_data != nullptr){
            delete m_data;
            m_data = nullptr;
        }
    }

    T* get(){
        return m_data;
    }

    //对象所有权被转移，对象本身不占有该指针
    T* release(){
        auto data = m_data;
        m_data = nullptr;
        return data;
    }

    //赋值新指针
    void reset(T* data = nullptr){
        if(m_data != data){
            delete m_data;
            m_data = data;
        }
    }

    T* operator -> (){
        return m_data;
    } 
    T& operator * (){
        return *m_data;
    } 

    void swap(UniquePtr<T>& other){
        auto data = other.m_data;
        other.m_data = m_data;
        m_data = data;
    }

    UniquePtr& operator = (const UniquePtr<T>& other) = delete;
    UniquePtr & operator = (UniquePtr<T>&& other){
        if(this == &other){
            return *this;
        }
        reset(other.relase());
        return *this;
    }

    //对数组包装
    T& operator [] (int i) const{   //重载下标运算符
        return m_data[i];
    }



private:
    T* m_data;
};

class Test{
public:
    Test() = default;
    ~Test(){
        std::cout<<"test is deleted"<<std::endl;
    }
    void name(const string& name){
        m_name = name;
    }
    string name() const{
        return m_name;
    }

private:
    string m_name;
};

int main(){

    auto p = new Test();
    UniquePtr<Test> up(p);
    //print:test is deleted
    p->name("jack");
    cout<<p->name()<<endl;
    up->name("tom");
    cout<<up->name()<<endl;
    //移动构造没禁
    UniquePtr<Test> up2(move(up));
    cout<<up2->name()<<endl;   

    UniquePtr<Test> up3(up2.release());
    cout<<up3->name()<<endl;     

    return 0;
}